/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
/*
 * Topology Viewer
 */

package cgl.narada.topology.viewer;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * This class consists of all the methods that are relevant to the calculation
 * related to the node-positions on the screen.
 */
public class PositionCalculation {
    public static double MAX_VALUE = Double.MAX_VALUE;

    public PositionCalculation() {

    }
    
    /**
     * Returns <code>List</code> of new positions to be assigned to all nodes
     * one level below inside the component
     * @param reference <code>Position</code> of a reference center about which
     *        other centers are being placed.
     * @param numberOfNodes number of components at particular level.
     * @param level level of a component in the four level hierarchy.
     * @return <code>List</code> of <code>Position</code> objects 
     */
    public static List getNewPositions(Position reference, int numberOfNodes,
				       int level) {
	List newPositions = new ArrayList();
	/* Total number of nodes is number of nodes already present in the list
	 * plus the new node to be inserted.
	 */
	double angleIncrement = 0.0;
	if (numberOfNodes != 0) {
	    angleIncrement = (Math.PI * 2) / numberOfNodes;
	}
	for (int i = 0; i < numberOfNodes; i++) {
	    double xDistance = 0.0;
	    double yDistance = 0.0;
	    double radiusOfInnerNode = 0.0;
	    if (numberOfNodes == 1) {
		xDistance = reference.getCenterX();
		yDistance = reference.getCenterY();
		radiusOfInnerNode = reference.getRadius() / 2;
	    } else {
		xDistance = reference.getCenterX() +
		    Math.cos(angleIncrement * i) 
		    * (reference.getRadius() / 2);
		yDistance = reference.getCenterY() +
		    Math.sin(angleIncrement * i) 
		    * (reference.getRadius() / 2);
		double distanceBetweenCenters = reference.getRadius() *
		    Math.sin(angleIncrement / 2);
		radiusOfInnerNode = distanceBetweenCenters * 0.45; 
	    }
	    Position position;
	    if (level == 4) {
		position = new Position(xDistance, yDistance,
					radiusOfInnerNode);
	    } else {
		position = new Position(xDistance, yDistance,
					radiusOfInnerNode, 
					getNodeColor(level));
	    }
	    newPositions.add(position);
	}
	return newPositions;
    }

    /**
     * Returns node color depending upon its level.
     * @param level level of a component in a four level hierarchy.
     * @return <code>Color</code> of a node at specified level.
     */
    public static Color getNodeColor(int level) {
	/*
	 * Decide the node color depending upon its level
	 */
	Color nodeColor = null;
	if (level == 4) {
	    nodeColor = new Color(245, 137, 172);
	} else if (level == 3) {
	    nodeColor = new Color(180, 250, 220);
	} else if (level == 2) {
	    nodeColor = new Color(255, 220, 180);
	} else if (level == 1) {
	    nodeColor = new Color(220, 220, 240);
	}
	return nodeColor;
    }

    /**
     * Returns component nearest to the specified coordinates.
     * @param nodeList <code>List</code> of components.
     * @param clickedX X-coordinate
     * @param clickedY Y-coordinate
     * @return nearest <code>Node</code>. null if no such node is found. 
     */ 
    public static Node getNearestNode(List nodeList, 
				      int clickedX, int clickedY) {
	Iterator it = nodeList.iterator();
	double distanceFromCenter = MAX_VALUE;
	Node closestNode = null; 
	while (it.hasNext()) {
	    Node node = (Node) it.next(); 
	    double distance = 
		Math.sqrt(((node.nodeLocation.getCenterX() - clickedX)
			   * (node.nodeLocation.getCenterX() - clickedX)) 
			  + ((node.nodeLocation.getCenterY() - clickedY)
			     * (node.nodeLocation.getCenterY() - clickedY)));
	    if ((distance < distanceFromCenter) 
		&& (distance <= node.nodeLocation.getRadius())) {
		distanceFromCenter = distance;
		closestNode = node;
	    }
	}
	return closestNode;
    }
};
